//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <bsp.h>
#include <init.h>
#include "8259A.h"

EXTERN_C DECL_CODEINIT void CDECL InitPIC()
{
    // Init master PIC
    OutbDelay(MASTER_PIC(ICW1_Port), ICW1 + ICW1_IC4);

    OutbDelay(MASTER_PIC(ICW2_Port), bsp.uIrqBase);

    OutbDelay(MASTER_PIC(ICW3_Port), ICW3_MASTER_IR);

    OutbDelay(MASTER_PIC(ICW4_Port), ICW4_uPM);

    // Init slave PIC
    OutbDelay(SLAVE_PIC(ICW1_Port), ICW1 + ICW1_IC4);

    OutbDelay(SLAVE_PIC(ICW2_Port), bsp.uIrqBase + 8);

    OutbDelay(SLAVE_PIC(ICW3_Port), ICW3_SLAVE_ID);

    OutbDelay(SLAVE_PIC(ICW4_Port), ICW4_uPM);
}

INLINE void EndOfInterrupt(irq_t irq)
{
    if (irq < 8) {
        Outb(MASTER_PIC(OCW2_Port), OCW2_SL + OCW2_EOI + irq);
    }
    else {
        Outb(SLAVE_PIC (OCW2_Port), OCW2_SL + OCW2_EOI + (irq - 8));
        Outb(MASTER_PIC(OCW2_Port), OCW2_SL + OCW2_EOI + SLAVE_IRQ);
    }
}

#define IRQ_FULL_MASK   0xfffb

STATIC irqs_t s_irqMask = IRQ_FULL_MASK;

EXTERN_C void CDECL BspMaskIrqs(irqs_t irqs, bool_t bEnable)
{
    if (bEnable)
        s_irqMask &= ~irqs;
    else
        s_irqMask |= irqs;

    if (irqs & 0x00ff)  Outb(MASTER_PIC(OCW1_Port), LOBYTE(s_irqMask));
    if (irqs & 0xff00)  Outb(SLAVE_PIC (OCW1_Port), HIBYTE(s_irqMask));
}

EXTERN_C void CDECL BspMaskAllIrqs(bool_t bEnable)
{
    s_irqMask = bEnable? 0x0000 : IRQ_FULL_MASK;

    Outb(MASTER_PIC(OCW1_Port), LOBYTE(s_irqMask));
    Outb(SLAVE_PIC (OCW1_Port), HIBYTE(s_irqMask));
}

EXTERN_C void CDECL BspAcknowledgeIrq(irq_t irq)
{
    EndOfInterrupt(irq);
}
